use std::fmt::{Debug, Display};

trait Summary {
    // 默认实现
    fn summarize(&self) -> String {
        format!("read more from {} ...", self.summarize_author())
    }

    fn summarize_author(&self) -> String;
}

struct Article {
    headline: String,
    location: String,
    author: String,
    content: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }

    fn summarize_author(&self) -> String {
        format!("{}", self.author)
    }
}

struct Tweet {
    username: String,
    content: String,
    reply: String,
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("{}: {}", self.username, self.content)
    }

    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }
}

// tarit作为参数, 类型前要加impl关键字
fn notify(item: impl Summary) {
    println!("news~ {}", item.summarize())
}

// trait约束, 等效于上面的写法
fn notify_more<T: Summary>(item1: T, item2: T) {
    println!("news1: {}, news2:{}", item1.summarize(), item2.summarize())
}

// 使用 + 指定多个约束
// 等效 fn notify_display(item: Summary + Display)
fn notify_display<T: Summary + Display>(item: T) {}

fn notify_multi<T, U>(item1: T, item2: U)
where
    T: Display + Clone,
    U: Clone + Debug,
{

}

// 返回trait


fn main() {
    // 
}


fn test_trait_object() {
    // 使用trait对象来存储不同类型的值到集合
    // 大小要确定， Box
    // 动态派发，dyn
    let list: Vec<Box<dyn Summary>> = vec![];

    // 使用泛型+trait约束, 只能存储某一个类型的数据到集合
}
